import React, { Component } from "react";
import {
  Form,
  Input,
  Modal,
  Row,
  Col,
  Button,
  Radio,
  Spin,
  Select,
  Table,
} from "antd";
import { openNotificationWithIcon } from "utils/comm";
import { connect } from "dva";
import ReactJson from "react-json-view";
import styles from "./ExternalData.less";

const { Option } = Select;

const formItemLayout = {
  labelCol: { span: 24 },
  wrapperCol: { span: 24 },
};

@connect(({ loading }) => ({
  loading,
}))
@Form.create()
class ExternalData extends Component {
  constructor(props) {
    super(props);
    this.openNotificationWithIcon = openNotificationWithIcon.bind(this);

    this.state = {
      data: [
        {
          code: "111",
          name: "数学",
        },
        {
          code: "222",
          name: "语文",
        },
      ],
      idPath: "code",
      valuePath: "name",
      listMap: ["code", "name"],
      column: [
        {
          title: "键 KEY",
          dataIndex: "code",
          render: (text) => <span title={text}>{text}</span>,
        },
        {
          title: "值 VALUE",
          dataIndex: "name",
          render: (text) => <span title={text}>{text}</span>,
        },
      ],
    };
  }

  componentDidMount() {
    const { selectedItem, form } = this.props;
    const { params } = selectedItem;
    if (params && JSON.stringify(params) !== "{}") {
      const payload = {
        url: params.url,
        headers: params.headers,
        requestMethod: params.requestMethod,
      };
      form.setFieldsValue(payload);
      this.getExecuteRequest(payload);
      const arrId = params.idPath.split("/");
      const arrValue = params.valuePath.split("/");

      this.setState(
        {
          idPath: arrId[arrId.length - 1],
          valuePath: arrValue[arrValue.length - 1],
        },
        () => {
          this.reviewListData();
        },
      );
    } else {
      this.setState({ firstEnter: true });
    }
  }

  handleOk = () => {
    const { onCancel, form, handleOptionsChange } = this.props;
    const { idPath, valuePath, data, listMap, firstEnter } = this.state;

    if (!idPath || !valuePath) {
      this.openNotificationWithIcon("error", "", "键KEY与值VALUE不能为空");
      return;
    }

    if (idPath === valuePath) {
      this.openNotificationWithIcon(
        "error",
        "",
        "键 KEY与值 VALUE不可选择相同值",
      );
      return;
    }

    if (firstEnter) {
      this.openNotificationWithIcon("error", "", "请先获取数据接口数据");
      return;
    }

    if (!listMap.includes(idPath) || !listMap.includes(valuePath)) {
      this.openNotificationWithIcon(
        "error",
        "",
        "数据无法绑定，请选择正确的键KEY与值VALUE",
      );
      return;
    }

    form.validateFields((err, values) => {
      if (err) {
        return;
      }

      if (data) {
        if (data instanceof Array) {
          if (data.length > 0) {
            // console.log(options);
            // console.log(params);
            handleOptionsChange({
              options: data.map(({[idPath]: key, [valuePath]: value }) => ({ value, key })),
              params: {
                headers: "",
                ...values,
                idPath: `datas/list[*]/${idPath}`,
                valuePath: `datas/list[*]/${valuePath}`,
              },
            });
            onCancel(false);
          } else {
            this.openNotificationWithIcon(
              "error",
              "",
              "返回结果数组为空，数据无法绑定",
            );
          }
        } else {
          this.openNotificationWithIcon(
            "error",
            "",
            "返回数据格式不对，数据无法绑定",
          );
        }
      } else {
        this.openNotificationWithIcon(
          "error",
          "",
          "返回结果为空，请先获取数据",
        );
      }
    });
  };

  onKeyChange = (v) => {
    this.setState({ idPath: v });
  };

  onValueChange = (v) => {
    this.setState({ valuePath: v });
  };

  // 调用外部url获取数据
  getData = () => {
    const { form } = this.props;
    form.validateFields((err, values) => {
      if (err) {
        return;
      }

      // console.log(values);
      this.getExecuteRequest(values);
      this.setState({ idPath: "", valuePath: "", column: [] });
    });
  };

  getExecuteRequest = (values) => {
    const { dispatch } = this.props;
    dispatch({
      type: "FormBuilder/executeRequest",
      payload: { headers: "", ...values },
    }).then(({ errCode, errMsg, datas }) => {
      if (errCode === 0 && datas.list instanceof Array) {
        const listMap = Object.keys(datas.list[0]);
        this.setState({ data: datas.list, listMap, firstEnter: false });
      } else {
        this.setState({
          data: [],
          listMap: [],
          idPath: "",
          valuePath: "",
        });
        this.openNotificationWithIcon("error", "", errMsg);
      }
    });
  };

  reviewListData = () => {
    const { idPath, valuePath } = this.state;

    if (!idPath) {
      this.openNotificationWithIcon("error", "", "键 KEY不能为空");
      return;
    }

    if (!valuePath) {
      this.openNotificationWithIcon("error", "", "值 VALUE不能为空");
      return;
    }

    if (idPath === valuePath) {
      this.openNotificationWithIcon(
        "error",
        "",
        "键 KEY与值 VALUE不可选择相同值",
      );
      return;
    }
    const newColumn = [
      {
        title: "键 KEY",
        dataIndex: idPath,
        render: (text) => <span title={text}>{text}</span>,
      },
      {
        title: "值 VALUE",
        dataIndex: valuePath,
        render: (text) => <span title={text}>{text}</span>,
      },
    ];
    this.setState({ column: newColumn });
  };

  handleCancel = (visible) => {
    const { onCancel, selectedItem } = this.props;
    const { params } = selectedItem;
    if (params && JSON.stringify(params) !== "{}") {
      onCancel(visible, false);
    } else {
      Modal.confirm({
        title: "是否取消配置外部数据",
        okText: "确认",
        cancelText: "取消",
        onOk: () => {
          onCancel(visible, true);
        },
      });
    }
  };

  render() {
    const { form, visible, loading } = this.props;
    const { data, idPath, valuePath, listMap, column, firstEnter } = this.state;

    const { getFieldDecorator } = form;

    const options = ["GET", "POST"];
    const dataLoading = loading.effects["FormBuilder/executeRequest"];

    // console.log(dataLoading);

    const spanAfter = (
      <span onClick={this.getData} style={{ cursor: "pointer" }}>
        获取数据
      </span>
    );

    return (
      <Modal
        title="外部数据"
        visible={visible}
        onOk={this.handleOk}
        onCancel={() => this.handleCancel(false)}
        width="800px"
        centered
        destroyOnClose
        className={styles.root}
        hideRequiredMark
        labelAlign="left"
        closable={false}
        maskClosable={false}
        footer={[
          <Button key="ok" type="primary" onClick={this.handleOk}>
            确定
          </Button>,
          <Button key="back" onClick={() => this.handleCancel(false)}>
            取消
          </Button>,
        ]}
      >
        <Row>
          <Col span={14}>
            <div className={styles.title}>数据来源</div>
            <Form {...formItemLayout}>
              <div className={styles.formItem}>
                <span className={styles.formLabel}>获取地址：</span>
                <Form.Item label="">
                  {getFieldDecorator("url", {
                    rules: [{ required: true, message: "请输入API 地址" }],
                    getValueFromEvent: (event) => {
                      return event.target.value.replace(/\s+/g, "");
                    },
                  })(<Input placeholder="API URL" addonAfter={spanAfter} />)}
                </Form.Item>
              </div>
              <div className={styles.formItem}>
                <span className={styles.formLabel}>请求头：</span>
                <Form.Item label="">
                  {getFieldDecorator("headers", {
                    rules: [],
                    getValueFromEvent: (event) => {
                      return event.target.value.replace(/\s+/g, "");
                    },
                  })(
                    <Input
                      placeholder="请输入请求头数据"
                      style={{ width: "260px" }}
                    />,
                  )}
                </Form.Item>
              </div>
              <div className={styles.formItem}>
                <span className={styles.formLabel}>请求方法：</span>
                <Form.Item label="" {...formItemLayout}>
                  {getFieldDecorator("requestMethod", {
                    initialValue: "GET" || null,
                    rules: [],
                  })(
                    <Radio.Group
                      options={options}
                      // defaultValue={["publisher"]}
                    />,
                  )}
                </Form.Item>
              </div>
            </Form>
            <div className={styles.row}>
              <span className={styles.boxContent}>
                {firstEnter && (
                  <span style={{ color: "red" }}>
                    接口返回数据格式需符合如下要求
                  </span>
                )}
                <Spin spinning={dataLoading || false}>
                  <ReactJson src={data} name={false} displayDataTypes={false} />
                </Spin>
              </span>
            </div>
          </Col>
          <Col span={10}>
            <div className={styles.title}>数据绑定设置</div>
            <div>
              <div className={styles.keyRow} style={{ marginBottom: "24px" }}>
                <span className={styles.key}>选择键 KEY</span>
                <Select
                  placeholder="选择键 KEY"
                  value={idPath}
                  onChange={this.onKeyChange}
                >
                  {listMap.map((item) => (
                    <Option key={item} value={item}>
                      {item}
                    </Option>
                  ))}
                </Select>
              </div>
              <div className={styles.keyRow}>
                <span className={styles.key}>选择值 VALUE</span>
                <Select
                  placeholder="选择值 VALUE"
                  value={valuePath}
                  onChange={this.onValueChange}
                >
                  {listMap.map((item) => (
                    <Option key={item} value={item}>
                      {item}
                    </Option>
                  ))}
                </Select>
              </div>
              <div className={styles.button}>
                <Button onClick={this.reviewListData}>点击预览</Button>
              </div>
            </div>
            <div className={styles.title}>数据绑定结果预览</div>
            <div className={styles.table}>
              <Table
                dataSource={data}
                columns={column}
                size="small"
                pagination={false}
                rowKey={idPath}
              />
            </div>
          </Col>
        </Row>
      </Modal>
    );
  }
}

export default ExternalData;
